#ifndef XG_ORACLECONNECT_H
#define XG_ORACLECONNECT_H
//////////////////////////////////////////////////////////////
#include <oci.h>
#include "DBConnect.h"

class OracleColumnData
{
public:
	ub2 size;
	ub2 type;
	ub2 indicator;
	OCIDefine* handle;
};

class OracleRowData : public RowData
{
	friend class OracleQueryResult;

	ub1* m_pBuffer = NULL;
	int m_iCurIndex = 0;
	int m_iColumCount = 0;
	OracleColumnData* m_pOracleColumnData = NULL;

	int getOffset(int index);

public:
	CONSTRUCTOR_FORBID_COPY(OracleRowData)

	bool isNull();
	~OracleRowData();
	string getString(int index);
	int getDataLength(int index);
	DateTime getDateTime(int index);
	int getData(int index, char* data, int len);
	bool getDateTime(DateTime& datetime, int index);
	OracleRowData(OracleColumnData* data, ub1* buffer, int cols);
};

class OracleQueryResult : public QueryResult
{
	friend class OracleConnect;

	OCIStmt* m_stmt = NULL;
	OCIError* m_pErr = NULL;
	int m_iColumCount = 0;
	int m_iBufferSize = 0;
	bool m_bFetchFirst = false;
	u_char* m_pSharedBuffer = NULL;
	OracleColumnData* m_pOracleColumnData = NULL;

public:
	CONSTRUCTOR_FORBID_COPY(OracleQueryResult)

	int rows();
	int cols();
	void close();
	sp<RowData> next();
	bool seek(int ofs);
	int getErrorCode();
	~OracleQueryResult();
	string getErrorString();
	string getColumnName(int index);
	bool getColumnData(ColumnData& data, int index);
	OracleQueryResult(OCIStmt* stmt, OCIError* err, OracleColumnData* data, int iColunCount, u_char* buffer, int iBufferSize);
};

class OracleConnect : public DBConnect
{
	friend class OracleQueryResult;

	static OCIEnv* s_pEnv;
	OCIError* m_pErr = NULL;
	OCIServer* m_pSrv = NULL;  
	OCISvcCtx* m_pSvc = NULL;

	static bool FreeHandle(dvoid* handle, int type);
	static bool AllocHandle(dvoid** handle, int type);

	int bind(void* stmt, const vector<DBData*>& vec);

public:
	CONSTRUCTOR_FORBID_COPY(OracleConnect)

	void close();
	bool commit();
	bool rollback();
	~OracleConnect();
	const char* getTableSQL();
	const char* getSystemName();
	bool begin(bool commited = true);
	bool setCharset(const string& charset);
	int getPrimaryKeys(vector<string>& vec, const string& tabname);
	bool connect(const string& host, int port, const string& name, const string& user, const string& password);

	int getErrorCode();
	string getErrorString();
	int execute(const string& sqlcmd);
	sp<QueryResult> query(const string& sqlcmd);
	int execute(const string& sqlcmd, const vector<DBData*>& vec);
	sp<QueryResult> query(const string& sqlcmd, const vector<DBData*>& vec);

	static bool Setup();
};
//////////////////////////////////////////////////////////////
#endif